#pragma once

#define MAX_MOVE_STEPS 13


#define BYTE  unsigned __int8
#define DWORD unsigned __int32
#define WORD  unsigned __int16
#define NULL  0

#define ULONGLONG unsigned __int64

#define EMPTY 0

#define WHITE_MAN ((BYTE)0x05)
#define BLACK_MAN ((BYTE)0x03)
#define WHITE_King ((BYTE)0x0D) // 13
#define BLACK_King ((BYTE)0x0B) // 11
#define MAX_FIGURE_NUMBER 255

#define FIGURE_AND ((BYTE)1)
#define	King_AND ((BYTE)0x08)
#define WHITEFIGURE_AND (((BYTE)4) | FIGURE_AND)
#define BLACKFIGURE_AND (((BYTE)2) | FIGURE_AND)


#define BORDER ((BYTE)0xf0)

#define IS_BLACKFIGURE(X) (((X) & BLACKFIGURE_AND) == BLACKFIGURE_AND)
#define IS_WHITEFIGURE(X) (((X) & WHITEFIGURE_AND) == WHITEFIGURE_AND)
#define IS_King(X) ((X) & King_AND)
#define IS_MAN(X)   (((X) & King_AND) == 0)
#define IS_EMPTY(X) ((X) == EMPTY)
#define IS_BORDER(X) ((X) == BORDER)
#define IS_FIGURE(X) ((X) & FIGURE_AND)
#define CHANGE_TO_King(X) ((X)<9 || (X)>36)
#define King_CHANGE_FLAG 0x8000

#define OPPOSITE_DIRECTION(X) ( -(X))


struct TSingleMove
{
public:
	BYTE numMoves; // filled in by DoMove function for quicker UndoMove
	BYTE MovePositions [MAX_MOVE_STEPS];
	BYTE RemovedFigures [MAX_MOVE_STEPS];
	BYTE RemovePositions [MAX_MOVE_STEPS];
	BYTE Crowned; // filled by DoMove function
};

// basic class containing moves
struct SMoveAnalysis
{
	bool bHasJumps;
	BYTE dwNumMoves;
private:
	TSingleMove Moves[MAX_MOVES];
public:
	TSingleMove* MovesInOrder[MAX_MOVES];

	SMoveAnalysis()
	{
		bHasJumps = false;
		ClearMoves();
	}

	virtual ~SMoveAnalysis()
	{
	}


	
	void inline ClearMoves()
	{
		dwNumMoves = 0;
		memset(Moves, 0, MAX_MOVES * sizeof(TSingleMove));
		memset(MovesInOrder, 0, MAX_MOVES*sizeof(TSingleMove*));
	}

	void inline BuildOrderOfMoves()
	{
		for(int i = 0; i < dwNumMoves; i++)
			MovesInOrder[i] = &(Moves[i]);
	}

	bool inline HasJumps()
	{
		return bHasJumps;
	}

	DWORD inline GetCount()
	{
		return dwNumMoves;
	}

	void inline GetMove(int idx, TSingleMove* pSingleMove)
	{
		memcpy(pSingleMove, MovesInOrder[idx], sizeof(TSingleMove));
	}

	void inline AddMove(BYTE indexSrc, BYTE indexTgr, bool bJump)
	{

		bHasJumps = bJump;

		register BYTE dwIndex = dwNumMoves++;
		Moves[dwIndex].MovePositions[0] = indexSrc;
		Moves[dwIndex].MovePositions[1] = indexTgr;
	}

	void inline AddMove(TSingleMove* pSingleMove, bool bJump)
	{
		bHasJumps = bJump;
		if(pSingleMove->MovePositions[MAX_MOVE_STEPS - 1] != 0)
		{
			assert(FALSE);
		}

		register BYTE dwIndex = dwNumMoves++;
		memcpy(&Moves[dwIndex], pSingleMove, sizeof(TSingleMove));
	}
};



void GenerateMoves(TGameBoard board, SMoveAnalysis* pMoveAnalysis, bool bWhite);
